<?php
namespace app\api\model;

use ethtool\Callback;
use think\Db;
use think\Model;
use think\Validate;
use Web3\Contract;
use Web3\Providers\HttpProvider;
use Web3\RequestManagers\HttpRequestManager;
use Web3\Utils;
use Web3\Web3;
use xtype\Ethereum\Client;

class XstModel extends Model
{
    protected $web3;
    protected $client;
    public function __construct($data = [])
    {
        parent::__construct($data);
        $this->client = new Client("https://mainnet.infura.io/v3/e4d43233309545f088944e2063908927");
    }

    //获取地址
    public function getAddress(){
       list($address, $privateKey) = $this->client->newAccount();
        $arr = array(
            "privateKey"=>$privateKey,
            "address" => $address
        );
        return $arr;
    }
    //获取ETH余额
    public function getbalance($address){
        $balance=$this->client->request("eth_getBalance",[$address,"latest"]);
        return round(hexdec(substr($balance,2))/1000000000000000000,4);
    }
    //转为16进制
    public function to16($num)
    {
        return "0x".base_convert($num, 10, 16);
    }
    //转为10进制
    public function to10($num)
    {
        return base_convert($num, 16, 10);
    }
    //eth转账
    function sendTransaction($from,$to,$value,$privateKeys,$uid)
    {
//        0x4319ff311d9370b39eaf69e5a970c6921ddb4782381262084a936377a5780387
        $this->client->addPrivateKeys([$privateKeys]);
        $value=Utils::toWei(strval($value), "ether");
        $trans = [
            "from" => $from,
            "to" => $to,
            "value" => $this->to16($value->value),
            "data" => '0x',
        ];
        $trans['gas'] = dechex(hexdec($this->client->eth_estimateGas($trans)) * 1.5);
        $trans['gasPrice'] = $this->client->eth_gasPrice();
        $trans['nonce'] = $this->client->eth_getTransactionCount($from, 'pending');
        $txid = $this->client->sendTransaction($trans);
        unset($trans["data"]);
        $trans["hash"]=$txid;
        $trans["uid"]=$uid;
        $trans["create_time"]=time();
        $res=Db::name("ethereum_log")->insert($trans);
        return $txid;
    }

    //获取代币余额
    public function getbalance_ccy(){
        vendor("./hubwiz/ethtool/src/Callback");
        $this->web3 = new Web3(new HttpProvider(new HttpRequestManager("https://mainnet.infura.io/v3/57031c59e2594c75bf053adbc3fc87fa",10)));
        $abi = file_get_contents( './token.abi');
        //合约地址
        $addr_he = "0xA34d29Cf8a06E8d05D22454cC33e5FBe7A3d3213";
        $contract = new Contract($this->web3->provider,$abi);
        $contract->at($addr_he);
        $cb = new Callback;
        //获取代币余额
        $opts = [

        ]; //不需要消耗gas
        $form = "0x0f17cb19db2b2d2414da1058aebd444c8e2aa033";
        $contract->call('balanceOf',$form,$opts,$cb);
        $balance = $cb->result['balance']->toString();
        echo 'balance' . $balance . PHP_EOL;
    }
    //代币交易
    public function transfer($form,$key,$amounts,$to,$uid){
        vendor("./hubwiz/ethtool/src/Callback");
        vendor("./hubwiz/ethtool/src/Credential");
        $this->web3 = new Web3(new HttpProvider(new HttpRequestManager("https://mainnet.infura.io/v3/e4d43233309545f088944e2063908927",10)));
        $abi = file_get_contents( './token.abi');
        //合约地址
        $addr_he = "0x793BF5B5d34151B276Ac212bfadDB915e3a47126";
        $contract = new Contract($this->web3->provider,$abi);
        $contract->at($addr_he);
        $cb = new Callback;
        //交易
        //用户地址
        $opts = [
            'from' => $form,
            'data' => '0x',
            'value' => 0,
            'key' => $key
        ];
        //金额
        $amount = $this->NumToStr($amounts*1000000000000000000);
        $contract->send('transfer',$to,$amount,$opts,$cb);
        if(isset($cb->error)){
            return $cb->error;
        }else{
            $trans= [
                'from' => $form,
                'value' => $amounts,
                'to' => $to,
                'uid' => $uid,
                'hash' =>$cb->result,
                'create_time' => time()
            ];
            $res=Db::name("ethereum_log")->insert($trans);
            return array("code"=>1,"message"=>"ok","hash"=>$cb->result);
        }
    }
  	 /**
     * 科学计数法转数字字符串
     * @param int $num   科学计数法
     * @throws WxPayException
     */
  	private function NumToStr($num) {
        if (stripos($num, 'e') === false)
            return $num;
        $num = trim(preg_replace('/[=\'"]/', '', $num, 1), '"'); //出现科学计数法，还原成字符串
        $result = "";
        while ($num > 0) {
            $v = $num - floor($num / 10) * 10;
            $num = floor($num / 10);
            $result = $v . $result;
        }
        return $result;
    }
}